#ifndef HJ_FRAME_STRUCTURE_BASE_NET_INCLUDE_CMQTTCLIENT_H_
#define HJ_FRAME_STRUCTURE_BASE_NET_INCLUDE_CMQTTCLIENT_H_
#include "CBaseNetHeader.h"
#include "mongoose.h"
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
/**
 *
 * Copyright(c), SuperHouse Co.,Ltd.
 * All rights reserved.
 *
 * @brief   mqtt 客服端封装
 * @note    -
 * @author  lth
 * @date    2021-12-18
 *
 */

BASENET_BEGIN_NAMESPACE


//回调函数结构体
typedef struct _tsMqttCb
{
	/**
	 * mqtt 消息回调 --用于高级功能
	 *
	 * @note
	 * @param[in] pMqtt    消息
	 * @param[in] m_pData 用户指针
	 *
	 */
	void(*mqttRecvCmd)(struct mg_mqtt_message *pMqtt,void *m_pData);

	/**
	 *数据回调
	 *
	 * @note
	 * @param[in] topics 主题
	 * @param[in] data 数据指针
	 * @param[in] len 数据长度
	 * @param[in] m_pData 用户指针
	 *
	 */
	void(*publishData)(string topics,string &msg,void *m_pData);

	/**
	 *连接状态回调
	 *
	 *@note
	 * @param[in] status 连接状态
	 * @param[in] m_pData 用户指针
	 */
	void (*conStatus)(bool status,void *m_pData);

	/**
	 *秒级定时器（提供业务使用，不能阻塞）
	 *
	 *@note
	 */
	void (*secondTime)(unsigned long second,void *m_pData);

	_tsMqttCb(){
		mqttRecvCmd = NULL;
		publishData = NULL;
		conStatus = NULL;
		secondTime = NULL;
	}

}tsMqttCb;

// mqtt 连接信息
typedef struct _tsMqttOpts {
	// Username, can be empty
	string user;
	// Password, can be empty
	string pass;
	// Client ID
	string client_id;
	 // Will topic
	string will_topic;
	 // Will message
	string will_message;
	_tsMqttOpts(){
		user = "";
		pass = "";
		client_id = "";
		will_topic = "";
		will_message = "";
	}
}tsMqttOpts;

// mqtt证书信息
typedef struct _tsTlsOpts {
  // CA certificate file. For both listeners and clients
  string ca;
  // Certificate Revocation List. For clients
  string crl;
  // Certificate
  string cert;
  // Certificate key
  string certkey;
  // Cipher list
  string ciphers;
  // If not empty, enables server name verification
  string srvname;

  _tsTlsOpts(){
	  ca = "";
	  crl = "";
	  cert ="";
	  certkey ="";
	  ciphers = "";
	  srvname = "";
  }

}tsTlsOpts;

class BASENET_API CMqttClient : public QThread
{
    Q_OBJECT
public:

	/**
	 * 构造函数
	 *
	 * @note
	 * @return -
	 */
	CMqttClient();

	/**
	 * 析构函数
	 *
	 * @note
	 * @return -
	 */
	~CMqttClient();

public:

	/**
	 * 启动MQTT客服端服务
	 *
	 * @note
	 * @return -
	 */
	bool start();

	/**
	 * 停止MQTT客服端服务
	 *
	 * @note
	 * @return -
	 */
	void stop();

	/**
	 *初始化产生
	 *
	 * @note
	 * @param[in] sOpts 服务器地址
	 * @param[in] sTlsOpts 授权账号
	 * @param[in] reconnectionTime 断开，或者连接失败重新连接时间
	 * @return -
	 */
	void init(string url,struct mg_mqtt_opts *sOpts,struct mg_tls_opts *sTlsOpts,int reconnectionTime=5000);

public:
	/**
	 * 订阅
	 *
	 * @param[in] topics 主题
	 * @return 消息ID 0失败
	 */
	uint16_t subscribes(const char *topics,int qos = 0);


	/**
	 * 取消订阅
	 *
	 * @param[in] topics 主题数组
	 * @param[in] topics_len 数组长度
	 * @return 消息ID 0失败
	 */
	uint16_t unSubscribes(char **topics,size_t topics_len);

	/**
	 * 发布消息
	 *
	 * @param[in] topics 主题
	 * @param[in] data   发布的数据
	 * @param[in] qos    消息质量
	 * @param[in] retain    消息是否保留
	 * @return 消息ID 0失败
	 */
	uint16_t publish(const char *topics,string &data,int qos=0,bool retain=false);

	/**
	 * 设置mqtt回调
	 *
	 * @param[in] topics 主题
	 */
	void setBack(tsMqttCb *back,void *data);

private:
	// 线程实现
	virtual void run();

public:
	// 定时器
	void __timer();

	/**
	 * mqtt 回调函数
	 *
	 * @note
	 * @param[in] c 连接
	 * @param[in] ev 事件
	 * @param[in] ev_data内容
	 *
	 * @return -
	 */
	void __mqttFn(struct mg_connection *c, int ev, void *ev_data);

private:
	// 连接管理器
	struct mg_mgr m_sMgr;
	// 定时器
	struct mg_timer m_sTimer;
	// 服务器地址
	string m_sUrl;
	// 连接配置
	tsMqttOpts        m_tOpts;
	// 连接配置
    struct mg_mqtt_opts m_sOpts;
    // ssl配置
    tsTlsOpts        m_tTlsOpts;
    // ssl配置
    struct mg_tls_opts m_sTlsOpts;
    // 初始化状态
    bool m_bInit;
    // 运行状态
    bool m_bRunStatus;
    // mqtt连接
    struct mg_connection *m_sMqttCon;
    // 断线重连接时间
    int m_iReConTime;
    // mqtt连接状态
    bool m_bConnestStatus;
private:
    // 记录心跳包发送的个数
    int m_iKeepLiveSendNum;
    // 计算时间
	unsigned long m_lPrev_second;
	// 定时器bug，并是不一秒回调一次，一秒可能回调多次，
	unsigned long m_lPrevSecondRun;
private:
    // 线程锁
    QMutex m_sLock;
private:
    // mqtt回调
    tsMqttCb *m_pBack;
    // mqtt回调指针
    void *m_pData;
};


BASENET_END_NAMESPACE





#endif // HJ_FRAME_STRUCTURE_BASE_NET_INCLUDE_CMQTTCLIENT_H_
